#pragma once
#include <iostream>
#include <memory>
#include <unistd.h>
#include "Socket.hpp"
#include<sys/poll.h>
using namespace SocketModule;
using namespace LogModule;
class PollServer

{
  const static int size = 4096;
  const static int defaultfd = -1;

public:
 PollServer(int port)
 :_listensock(std::make_unique<TcpSocket>()),
 _isrunning(false)
 {
  
   _listensock->BuildTcpSocketMetond(port);
   for(int i=0;i<size;i++)
   {
    _fds[i].fd=defaultfd;
    _fds[i].events=0;
    _fds[i].revents=0;

   }
   _fds[0].fd=_listensock->Fd();
   _fds[0].events=POLLIN;
 }
 void Start()
 {
   int timeout=-1;
   _isrunning=true;
   while(_isrunning)
   {
    Printfd();
    int n=poll(_fds,size,timeout);
    if(n==-1)
    {
      LOG(LogLevel::ERROR)<<"poll error";
    }
    else if(n==0)
    {
      LOG(LogLevel::INFO)<<"poll time out....";
    }
    else{
      LOG(LogLevel::INFO)<<"有事件就绪了。。。,n"<<n;
      Dispatcher();

    }
   }
   _isrunning=false;
 }
 void Dispatcher()
 {
   for (int i = 0; i < size; i++)
    {
      if (_fds[i].fd == defaultfd)
        continue;
      if (_fds[i].revents&POLLIN)
      {
        if (_fds[i].fd == _listensock->Fd())
        {
          Accepter();
        }
        else
        {
          
          Recver( i);
        }
      }
    }
 }
 void Accepter()
 {
    InetAddr client;
    int sockfd = _listensock->Accept(&client);
    if (sockfd >= 0)
    {
      int pos = 0;
      LOG(LogLevel::INFO) << "get a new link, sockfd: "
                                << sockfd << ", client is: " << client.StringAddr();
      for (; pos < size; pos++)
      {
        if (_fds[pos].fd == defaultfd)
          break;
      }
      if (pos == size)
      {
        LOG(LogLevel::INFO) << "select server full";
        close(sockfd);
      }
      else
      {
        _fds[pos].fd = sockfd;
        _fds[pos].events=POLLIN;
        _fds[pos].revents=0;
      }
    }
 }
 void Recver(int pos)
 {
   char buffer[1024];
    ssize_t n = recv(_fds[pos].fd, buffer, sizeof(buffer) - 1, 0);
    if (n > 0)
    {
      buffer[n] = 0;
  
      std::cout << "client say@ " << buffer << std::endl;
    }
    else if (n == 0)
    {
      LOG(LogLevel::INFO) << "client quit...";
    
      close(_fds[pos].fd);
      _fds[pos].fd=defaultfd;
      _fds[pos].events=0;
      _fds[pos].revents=0;
    }
    else
    {
      LOG(LogLevel::ERROR) << "recv error";
       close(_fds[pos].fd);
      _fds[pos].fd=defaultfd;
      _fds[pos].events=0;
      _fds[pos].revents=0;
    }
 }
 void Printfd()
  {
    std::cout << "_fd_array[]: ";
    for (int i = 0; i < size; i++)
    {
      if (_fds[i].fd == defaultfd)
        continue;
      std::cout << _fds[i].fd << " ";
    }
    std::cout << "\r\n";
  }
  void Stop()
  {
    _isrunning = true;
  }
  ~PollServer()=default;
private:
  std::unique_ptr<Socket> _listensock;
  bool _isrunning;

  struct pollfd _fds [size];

  
};